﻿using ConfigInfoWebPlatform.API.BusinessCommon;
using ConfigInfoWebPlatform.API.DBCommon;
using ConfigInfoWebPlatform.API.HubMessage;
using ConfigInfoWebPlatform.API.ViewModel;
using ConfigInfoWebPlatform.Model;
using ConfigInfoWebPlatform.Model.Model;
using ConfigInfoWebPlatform.Nlog;
using FileSecretAssemblyStandard;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;
using static System.Net.Mime.MediaTypeNames;

namespace ConfigInfoWebPlatform.API.Controllers
{


    /// <summary>
    /// 流程数据解析
    /// </summary>
    [Route("Manager/ProcessCfgFile")]
    [ApiController]
    public class ProcessCfgFileController : ControllerBase
    {
        readonly LogHelper _log;
        readonly string configRootPath;
        readonly string initDB;
        readonly InterfaceFileSecret FileSecret;
        private string backupRootPath;
        readonly HubMessageServer hubMessageServer;

        /// <summary>
        /// 应用路径
        /// </summary>
        public static readonly DirectoryInfo AppDirectory = new DirectoryInfo(System.AppDomain.CurrentDomain.BaseDirectory);
        /// <summary>
        /// 流程处理控制
        /// </summary>
        public ProcessCfgFileController(LogHelper logHelper, IConfiguration configuration, InterfaceFileSecret fileSecret, HubMessageServer hubMessage)
        {
            _log = logHelper;
            configRootPath = configuration["AppSetting:configPath"].ToString();
            backupRootPath = configRootPath.Replace("wordparse2.0", "备份");
            initDB = configuration["AppSetting:initDB"].ToString();
            FileSecret = fileSecret;
            System.Runtime.CallContext.SetData("baseDirectory", AppContext.BaseDirectory);
            hubMessageServer = hubMessage;
        }
        /// <summary>
        /// 获取流程数据源
        /// </summary>
        /// <returns></returns>
        [HttpGet("Index")]
        public JsonResult Index(string dir, int page, int limit)
        {
            if (string.IsNullOrEmpty(dir))
            {
                return new JsonResult("");
            }
            var fname = Request.Query["fname"];
            var note = Request.Query["note"];
            //获取用户信息
            UserInfoModel user = new UserInfoModel();
            var userJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["user"]);
            user = Newtonsoft.Json.JsonConvert.DeserializeObject<UserInfoModel>(userJsonStr);
            //获取用户角色操作权限
            DAL_Role dal_Role = new DAL_Role();
            var isOperate = dal_Role.GetOperateAuthorityByRid(user.R_id);
            //获取版本信息
            VersionModel version = new VersionModel();
            var versionJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["version"]);
            version = Newtonsoft.Json.JsonConvert.DeserializeObject<VersionModel>(versionJsonStr);
            var versionPath = version?.Catalogue == "dev"
                                ? ""
                                : version?.Catalogue;
            string filepath = Path.Combine(configRootPath, versionPath, dir).Replace("\\", "/");
            // 获取导航功能ID
            DAL_ProgramNavicat navicatDal = new DAL_ProgramNavicat();
            
            if (!Directory.Exists(filepath))
            {
                Directory.CreateDirectory(filepath);
            }
            
            // 配置文件总列表
            ConfigFileList configFileList = new ConfigFileList();
            // 流程配置文件信息
            List<ConfigFileInfoModel> processCfgFileInfos = new List<ConfigFileInfoModel>();
            DAL_ConfigFile configFileDal = new DAL_ConfigFile();
            // 获取流程配置的文件结构
            Expression<Func<ConfigFiles, bool>> where = null;
            where = where.And(x => x.ParentPath == dir && x.Ctype == "D");
            if (!string.IsNullOrWhiteSpace(fname))
                where = where.And(x => x.Name.Contains(fname));
            if (!string.IsNullOrWhiteSpace(note))
                where = where.And(x => x.Note.Contains(note));

            processCfgFileInfos = configFileDal.GetConfigFilesByFilter(where);
            // 根据入参获取案件类型
            string caseType = Path.GetFileNameWithoutExtension(dir);

            configFileList.processCfgFiles = processCfgFileInfos;
            List<ConfigFileInfoModel> re = new List<ConfigFileInfoModel>();
            if (page > 0 && limit > 0)
            {
                // 获取页面的数据
                if (configFileList.processCfgFiles != null && configFileList.processCfgFiles.Count > 0)
                {
                    re = configFileList.processCfgFiles.Skip((page - 1) * limit).Take(limit).ToList();
                }
            }
            else
            {
                re = configFileList.processCfgFiles;
            }

            return new JsonResult(new { code = 0, msg = "success", count = configFileList.processCfgFiles.Count, isOperate = user.Name == "admin" ? 1 : isOperate, data = re });
        }

        /// <summary>
        /// 获取流程数据
        /// </summary>
        /// <returns></returns>
        [HttpGet("procefile")]
        public JsonResult ProceFile(string dir, string curdir)
        {
            if (string.IsNullOrEmpty(dir))
            {
                return new JsonResult("");
            }
            var start = Request.Query["start"];
            var end = Request.Query["end"];
            var fname = Request.Query["fname"];
            var fpath = Request.Query["fpath"];
            //获取用户信息
            UserInfoModel user = new UserInfoModel();
            var userJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["user"]);
            user = Newtonsoft.Json.JsonConvert.DeserializeObject<UserInfoModel>(userJsonStr);
            //获取版本信息
            VersionModel version = new VersionModel();
            var versionJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["version"]);
            version = Newtonsoft.Json.JsonConvert.DeserializeObject<VersionModel>(versionJsonStr);
            var versionPath = version?.Catalogue == "dev"
                                ? ""
                                : version?.Catalogue;
            string filepath = Path.Combine(configRootPath, versionPath, dir).Replace("\\", "/");
            if (!Directory.Exists(filepath))
            {
                Directory.CreateDirectory(filepath);
            }
            //获取用户角色操作权限
            DAL_Role dal_Role = new DAL_Role();
            var isOperate = dal_Role.GetOperateAuthorityByRid(user.R_id);
            // 获取导航功能ID
            DAL_ProgramNavicat navicatDal = new DAL_ProgramNavicat();
            // 配置文件总列表
            ConfigFileList configFileList = new ConfigFileList();
            // 流程配置文件信息
            List<ConfigFileInfoModel> processCfgFileInfos = new List<ConfigFileInfoModel>();
            DAL_ConfigFile configFileDal = new DAL_ConfigFile();
            var sourceDir = $"{dir}/{curdir}";
            Expression<Func<ConfigFiles, bool>> where = null;
            where = where.And(x => x.ParentPath == sourceDir && x.Ctype == "F");
            processCfgFileInfos = configFileDal.GetConfigFilesByFilter(where);


            // 获取流程配置的文件结构
            configFileList.processCfgFiles = processCfgFileInfos;
            return new JsonResult(new { code = 0, msg = "success", count = configFileList.processCfgFiles.Count, isOperate=user.Name=="admin"? 1: isOperate, data = configFileList.processCfgFiles });
        }

        /// <summary>
        /// 获取分析流程配置详情
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        [HttpGet("analysisdetail")]
        public ActionResult AnalysisDetail(string fileName)
        {
            //获取用户信息
            UserInfoModel user = new UserInfoModel();
            var userJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["user"]);
            user = Newtonsoft.Json.JsonConvert.DeserializeObject<UserInfoModel>(userJsonStr);
            //获取用户角色操作权限
            DAL_Role dal_Role = new DAL_Role();
            var isOperate = dal_Role.GetOperateAuthorityByRid(user.R_id);
            VersionModel version = new VersionModel();
            var versionJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["version"]);
            version = Newtonsoft.Json.JsonConvert.DeserializeObject<VersionModel>(versionJsonStr);
            var versionPath = version?.Catalogue == "dev"
                                ? ""
                                : version?.Catalogue;
            string rootconfigtemp = Path.Combine(configRootPath, versionPath, fileName);

            Tuple<string, string> logDic = Tuple.Create<string, string>("applicationname", "systemplatform");
            List<Step> stepList = new List<Step>();
            if (System.IO.File.Exists(rootconfigtemp))
            {
                FileInfo fileInfo = new FileInfo(rootconfigtemp);
                if (fileInfo.Length > 0)
                {
                    string xmlContent = FileSecret.DecryptFileToContent(rootconfigtemp);
                    ProcessViewModel processModel = CommonHandle.DeserializeToObject<ProcessViewModel>(xmlContent);
                    if (processModel.Analysis == null)
                    {
                        XDocument xdocument = XDocument.Parse(xmlContent);
                        RootView oldRoot = CommonHandle.DeserializeToObject<RootView>(xmlContent);
                        XElement root = xdocument.Element("root");
                        XElement analysis = new XElement("analysis");
                        root.Add(analysis);

                        XElement optimize = new XElement("optimize");
                        root.LastNode.AddAfterSelf(optimize);
                        if (oldRoot.Step != null && oldRoot.Step.Any())
                        {
                            var oldStepStr = JsonConvert.SerializeObject(oldRoot.Step);
                            List<XElement> steps =root.Descendants().Where(x => x.Name.LocalName == "step").ToList();
                            foreach (XElement element in steps)
                            {
                                element.SetAttributeValue("groupstepcode", "");
                                element.SetAttributeValue("steptype", "2");
                                analysis.Add(element);
                            }
                            stepList = JsonConvert.DeserializeObject<List<Step>>(oldStepStr);
                            foreach (Step step in stepList)
                            {
                                step.GroupStepCode = string.Empty;
                                step.StepType = 2;
                            }
                            stepList = stepList.OrderBy(x => x.Number).ToList();
                        }

                        List<XElement> delSteps = root.Elements().Where(x=>x.Name.LocalName=="step").ToList();

                        if (delSteps != null && delSteps.Any())
                        {
                            foreach (XElement delElement in delSteps)
                            {
                                delElement.Remove();
                            }
                        }

                        xdocument.Save(rootconfigtemp);
                        this.EncryptFileToFile(rootconfigtemp, rootconfigtemp);
                    }
                    else
                    {
                        if (processModel.Analysis.Steps != null && processModel.Analysis.Steps.Any())
                        {
                            stepList = processModel.Analysis.Steps.OrderBy(x => Convert.ToInt32(x.Number)).ToList();
                        }
                    }
                }
                else
                {
                    return new JsonResult(new { code = 0, msg = "找到文件，但是文件内容为空！", count = 0, isOperate = user.Name == "admin" ? 1 : isOperate, data = stepList });
                }
            }
            else
            {
                return new JsonResult(new { code = 0, msg = "未找到对应的文件内容信息", count = 0, isOperate = user.Name == "admin" ? 1 : isOperate, data = new RootView().Step });
            }
            return new JsonResult(new { code = 0, msg = "成功", count = stepList.Count, isOperate = user.Name == "admin" ? 1 : isOperate, data = stepList });
        }

        /// <summary>
        /// 获取优选流程配置详情
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        [HttpGet("optimizedetail")]
        public ActionResult OptimizeDetail(string fileName)
        {
            //获取用户信息
            UserInfoModel user = new UserInfoModel();
            var userJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["user"]);
            user = Newtonsoft.Json.JsonConvert.DeserializeObject<UserInfoModel>(userJsonStr);
            //获取用户角色操作权限
            DAL_Role dal_Role = new DAL_Role();
            var isOperate = dal_Role.GetOperateAuthorityByRid(user.R_id);
            VersionModel version = new VersionModel();
            var versionJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["version"]);
            version = Newtonsoft.Json.JsonConvert.DeserializeObject<VersionModel>(versionJsonStr);
            var versionPath = version?.Catalogue == "dev"
                                ? ""
                                : version?.Catalogue;
            string rootconfigtemp = Path.Combine(configRootPath, versionPath, fileName);

            Tuple<string, string> logDic = Tuple.Create<string, string>("applicationname", "systemplatform");
            if (System.IO.File.Exists(rootconfigtemp))
            {
                FileInfo fileInfo = new FileInfo(rootconfigtemp);
                if (fileInfo.Length > 0)
                {
                    string xmlContent = FileSecret.DecryptFileToContent(rootconfigtemp);
                    ProcessViewModel root = CommonHandle.DeserializeToObject<ProcessViewModel>(xmlContent);
                    if (root.Optimize != null)
                    {
                        List<Step> stepList = GetOptimizeSteps(root.Optimize);
                        stepList = stepList.OrderBy(x => Convert.ToDecimal(x.Number)).ToList();
                        bool isHave = stepList.Any(x => x.StepType == 1);
                        _log.WriteLog(LogHelper.logType.Debug, "ProcessCfgFileController---OptimizeDetail方法:找到" + fileName + "文件，并将其内容返回给前端。");
                        return new JsonResult(new { code = 0, msg = "成功", count = stepList.Count, isOperate = user.Name == "admin" ? 1 : isOperate, data = stepList, isHide = isHave });
                    }
                    else
                    {
                        return new JsonResult(new { code = 0, msg = "成功", count = 0, isOperate = user.Name == "admin" ? 1 : isOperate, data = new List<Step>(), isHide = false });
                    }
                }
                else
                {
                    _log.WriteLog(LogHelper.logType.Debug, "ProcessCfgFileController---OptimizeDetail方法:" + fileName + "文件为空");
                    return new JsonResult(new { code = 0, msg = "找到文件，但是文件内容为空！", count = 0, isOperate = user.Name == "admin" ? 1 : isOperate, data = new RootView().Step, isHide = false });
                }
            }
            else
            {
                _log.WriteLog(LogHelper.logType.Debug, "ProcessCfgFileController---OptimizeDetail方法:未找到" + fileName + "文件！");
                return new JsonResult(new { code = 0, msg = "未找到对应的文件内容信息", count = 0, isOperate = user.Name == "admin" ? 1 : isOperate, data = new RootView().Step, isHide = false });
            }
        }

        /// <summary>
        /// 加载优选流程节点数据
        /// </summary>
        private List<Step> GetOptimizeSteps(Optimize optimize)
        {
            List<Step> steps = new List<Step>();
            if (optimize.GroupSteps != null && optimize.GroupSteps.Any())
            {
                foreach (var gp in optimize.GroupSteps)
                {
                    var start = Convert.ToDouble(gp.Start);
                    double stepIndex = start > 0 ? Convert.ToDouble(gp.Start) - 0.1 : 0;
                    Step step = new Step();
                    step.Number = stepIndex.ToString();
                    step.ExecuteFile = string.Empty;
                    step.ExecuteType = string.Empty;
                    step.Code = gp.Code;
                    step.Zh_cn = gp.Zh_cn;
                    step.StepType = gp.StepType;
                    step.GroupStepCode = "oproot";
                    steps.Add(step);
                    if (gp.Steps != null && gp.Steps.Any())
                    {
                        steps.AddRange(gp.Steps.ToList());
                    }
                }
            }

            if (optimize.Steps != null && optimize.Steps.Any())
            {
                steps.AddRange(optimize.Steps.ToList());
            }
            return steps;
        }

        /// <summary>
        /// 更新排序功能
        /// </summary>
        /// <returns></returns>
        [HttpPost("updateitems")]
        public ActionResult UpdateItems()
        {
            //获取用户信息
            UserInfoModel user = new UserInfoModel();
            var userJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["user"]);
            user = Newtonsoft.Json.JsonConvert.DeserializeObject<UserInfoModel>(userJsonStr);
            //获取版本信息
            VersionModel version = new VersionModel();
            var versionJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["version"]);
            version = Newtonsoft.Json.JsonConvert.DeserializeObject<VersionModel>(versionJsonStr);
            var versionPath = version?.Catalogue == "dev"
                                ? ""
                                : version?.Catalogue;
            // 获取请求过来的json数据
            var sr = new StreamReader(Request.Body);
            var stream = sr.ReadToEnd();

            // 将json数据转成对应的实体
            //string jsonstr=Base64Helper.DeCodeBase64(65001, stream);
            var delItemInfo = Newtonsoft.Json.JsonConvert.DeserializeObject<List<DelProcessCfgFileItemModel>>(stream);
            if (delItemInfo.Count > 0)
            {
                // 解密文件路径
                string fileP = Base64Helper.DeCodeBase64(65001, delItemInfo[0].filePath);
                string filePTemp = Path.Combine(configRootPath,versionPath, fileP.TrimStart('\\')).Replace("\\","/");
                if (System.IO.File.Exists(filePTemp))
                {
                    FileInfo fileInfo = new FileInfo(filePTemp);
                    if (fileInfo.Length > 0)
                    {
                        // 读取配置文件，并查找到number=json数据传过来的number，之后删除查找到的节点
                        string xmlContent = FileSecret.DecryptFileToContent(filePTemp);
                        XDocument xdocument = XDocument.Parse(xmlContent);
                        var reNodes = xdocument.Element("root").Elements().ToList();
                        foreach (var mouditem in delItemInfo)
                        {
                            reNodes.FirstOrDefault(a => a.Attribute("executefile").Value == Base64Helper.DeCodeBase64(65001, mouditem.moduleFile))?.SetAttributeValue("number", mouditem.number);
                        }
                        //重新排序
                        //reNodes = reNodes.OrderBy(a => a.Attribute("number").Value).ToList();
                        reNodes = reNodes.OrderBy(a => Convert.ToInt32(a.Attribute("number").Value)).ToList();
                        //删除原来的节点信息
                        xdocument.Element("root").RemoveAll();
                        //重新添加当前信息
                        foreach (var item in reNodes)
                        {
                            xdocument.Root.Add(item);
                        }
                        // 保存配置文件
                        xdocument.Save(filePTemp);
                        this.EncryptFileToFile(filePTemp, filePTemp);
                        _log.WriteLog(LogHelper.logType.Debug, "ProcessCfgFileController---UpdateItems方法：流程配置文件" + fileP + "更新了number=" + string.Join(",", delItemInfo.Select(a => a.number)) + "的项!");
                    }
                }
                else 
                {
                    return BadRequest("未找到对应文件！");
                }
            }
            return new JsonResult("成功！");
        }
        /// <summary>
        /// 删除流程配置文件中的某一项
        /// </summary>
        [HttpPost("deleteitem")]
        public IActionResult DeleteItem()
        {
            //获取用户信息
            UserInfoModel user = new UserInfoModel();
            var userJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["user"]);
            user = Newtonsoft.Json.JsonConvert.DeserializeObject<UserInfoModel>(userJsonStr);
            //获取版本信息
            VersionModel version = new VersionModel();
            var versionJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["version"]);
            version = Newtonsoft.Json.JsonConvert.DeserializeObject<VersionModel>(versionJsonStr);
            var versionPath = version?.Catalogue == "dev"
                                ? ""
                                : version?.Catalogue;
            string fileName = Request.Form["fileName"];
            string number = Request.Form["number"];
            string processType = Request.Form["processType"];
            string groupCode = Request.Form["groupCode"];
            string fileFullName = Path.Combine(configRootPath, versionPath, fileName);
            string modulePath = string.Empty;
            string moduleCode = string.Empty;
            if (System.IO.File.Exists(fileFullName))
            {
                FileInfo fileInfo = new FileInfo(fileFullName);
                if (fileInfo.Length > 0)
                {
                    // 读取配置文件，并查找到number=json数据传过来的number，之后删除查找到的节点
                    string xmlContent = FileSecret.DecryptFileToContent(fileFullName);
                    XDocument xdocument = XDocument.Parse(xmlContent);
                    XElement root = xdocument.Element("root");
                    XElement delNode = root.Descendants().FirstOrDefault(x => x.Name.LocalName == "step" && x.Attribute("number").Value == number);
                    if (delNode != null)
                    {
                        if (!string.IsNullOrWhiteSpace(groupCode))
                        {
                            XElement groupNode = root.Descendants().FirstOrDefault(x => x.Name.LocalName == "groupstep" && x.Attribute("code").Value == groupCode);
                            if (groupNode != null)
                            {
                                int start = Convert.ToInt32(groupNode.Attribute("start").Value);
                                int end = Convert.ToInt32(groupNode.Attribute("end").Value);
                                if (start < end)
                                    groupNode.Attribute("end").Value = (end - 1).ToString();
                            }
                        }
                        modulePath = delNode.Attribute("executefile").Value;
                        moduleCode = delNode.Attribute("code").Value;
                        delNode.Remove();
                        // 保存配置文件
                        xdocument.Save(fileFullName);
                        this.EncryptFileToFile(fileFullName, fileFullName);
                        DeleteModuleNode(fileName, modulePath, moduleCode);
                        _log.WriteLog(LogHelper.logType.Info, $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}用户{user.Name}删除了流程配置文件{fileName}中number={number}的配置项!");
                        // 修改对应模块配置文件下的索引文件
                        UpdateMoudleIndex(fileFullName, "D", Convert.ToInt32(number), groupCode, processType);
                    }
                    else
                    {
                        return new JsonResult(ReturnInfo.Fail("未找到该模块配置项"));
                    }

                }
                return new JsonResult(ReturnInfo.Success("删除成功"));

            }
            else
            {
                return new JsonResult(ReturnInfo.Fail("未找到相关文件"));
            }

        }

        /// <summary>
        /// 删除流程下分组模块
        /// </summary>
        /// <returns></returns>
        [HttpPost("deletegroupitem")]
        public IActionResult DeleteGroupItem()
        {

            //获取用户信息
            UserInfoModel user = new UserInfoModel();
            var userJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["user"]);
            user = Newtonsoft.Json.JsonConvert.DeserializeObject<UserInfoModel>(userJsonStr);
            //获取版本信息
            VersionModel version = new VersionModel();
            var versionJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["version"]);
            version = Newtonsoft.Json.JsonConvert.DeserializeObject<VersionModel>(versionJsonStr);
            var versionPath = version?.Catalogue == "dev"
                                ? ""
                                : version?.Catalogue;
            string fileName = Request.Form["fileName"];
            string processType = Request.Form["processType"];
            string groupCode = Request.Form["groupCode"];
            string fileFullName = Path.Combine(configRootPath, versionPath, fileName);
            if (System.IO.File.Exists(fileFullName))
            {
                FileInfo fileInfo = new FileInfo(fileFullName);
                if (fileInfo.Length > 0)
                {
                    // 读取配置文件，并查找到number=json数据传过来的number，之后删除查找到的节点
                    string xmlContent = FileSecret.DecryptFileToContent(fileFullName);
                    XDocument xdocument = XDocument.Parse(xmlContent);
                    XElement root = xdocument.Element("root");
                    XElement delNode = root.Descendants().FirstOrDefault(x => x.Name.LocalName == "groupstep" && x.Attribute("code").Value == groupCode);
                    if (delNode != null)
                    {
                        int end = Convert.ToInt32(delNode.Attribute("end").Value);
                        List<XElement> delSteps = delNode.Descendants().Where(x => x.Name.LocalName == "step").ToList();
                        if (delSteps != null && delSteps.Any())
                        {
                            delNode.RemoveNodes();
                        }
                        delNode.Remove();
                        // 保存配置文件
                        xdocument.Save(fileFullName);
                        this.EncryptFileToFile(fileFullName, fileFullName);
                        _log.WriteLog(LogHelper.logType.Info, $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}用户{user.Name}删除了流程配置文件{fileName}中code={groupCode}的配置项!");
                        // 修改对应模块配置文件下的索引文件
                        UpdateMoudleIndex(fileFullName, "D", end, groupCode, processType);
                    }
                    else
                    {
                        return new JsonResult(ReturnInfo.Fail("未找到该模块配置项"));
                    }

                }
                return new JsonResult(ReturnInfo.Success("删除成功"));

            }
            else
            {
                return new JsonResult(ReturnInfo.Fail("未找到相关文件"));
            }
        }

        /// <summary>
        /// 流程配置文件添加步骤，该控制器方法只起到一个给前端页面传送文件名的作用
        /// </summary>
        /// <param name="fileName">文件名</param>
        /// <returns></returns>
        [HttpGet("additem")]
        public ActionResult AddItem(string fileName, string processType)
        {
            //获取用户信息
            UserInfoModel user = new UserInfoModel();
            var userJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["user"]);
            user = Newtonsoft.Json.JsonConvert.DeserializeObject<UserInfoModel>(userJsonStr);
            //获取版本信息
            VersionModel version = new VersionModel();
            var versionJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["version"]);
            version = Newtonsoft.Json.JsonConvert.DeserializeObject<VersionModel>(versionJsonStr);
            var versionPath = version?.Catalogue == "dev"
                                ? ""
                                : version?.Catalogue;
            #region 获取当前文件step节点的序号，得到下一步的序号
            string stepNo = "";
            try
            {
                string fileNameTemp=Path.Combine(configRootPath,versionPath,fileName);
                string xmlContent = FileSecret.DecryptFileToContent(fileNameTemp);
                XDocument xdocument = XDocument.Parse(xmlContent);
                List<XElement> stepNodes = new List<XElement>();
                var stepNodes1 = xdocument.Element("root").Elements().ToList();
                XElement root = xdocument.Element("root");
                stepNodes = root.Descendants().Where(x => x.Name.LocalName == "step").ToList();
                if (stepNodes.Count == 0)
                {
                    stepNo = "1";
                }
                else
                {
                    //List<XElement> filterRe = stepNodes.OrderByDescending(a => a.Attribute("number").Value).ToList();
                    List<XElement> filterRe = stepNodes.OrderByDescending(a =>Convert.ToInt32(a.Attribute("number").Value)).ToList();
                    stepNo = (Convert.ToInt32(filterRe[0].Attribute("number").Value) + 1).ToString();
                }
            }
            catch (Exception ex)
            {
                _log.WriteLog(LogHelper.logType.Debug, "ProcessCfgController-AddItem方法：出现异常" + ex.Message);
            }
            #endregion

            #region 获取模块信息(分析模块与公共模块)
            // 模块集合
            List<ProgramNavicatModel> moduleList = new List<ProgramNavicatModel>();
            DAL_ProgramNavicat dAL_ProgramNavicat = new DAL_ProgramNavicat();
            // 获取分析模块配置的文件结构
            List<ProgramNavicatModel> modules = new List<ProgramNavicatModel>();

            if (processType=="analysis")
            {
                //int programId = dAL_ProgramNavicat.GetProgramId(@"config\moduleconfig\analysismoduleconfig");
                modules = dAL_ProgramNavicat.GetChildProgram(1003000000000000);
                modules.ForEach(a => a.Name += "_A");
            }
            else if(processType=="optimize")
            {
                modules = dAL_ProgramNavicat.GetChildProgram(1004000000000000);
                modules.ForEach(a => a.Name += "_O");
            }
            moduleList.AddRange(modules);

            // 获取公共模块的配置文件结果
            //programId = dAL_ProgramNavicat.GetProgramId(@"config\commoncfg");
            List<ProgramNavicatModel> commonModule = new List<ProgramNavicatModel>();
            commonModule = dAL_ProgramNavicat.GetChildProgram(1005000000000000);
            // 将分析模块配置信息与公共模块配置信息合并，之后遍历合并的模块
            commonModule.ForEach(c => c.Name += "_C");
            moduleList.AddRange(commonModule);
            #endregion
            return new JsonResult(new {stepnum= stepNo,data=moduleList });
        }

        /// <summary>
        /// 获取指定目录下的目录或是文件，当传入的目录已经没有子目录就返回文件列表
        /// </summary>
        /// <param name="parentDir">父级目录</param>
        /// <returns>子目录或是文件名的集合字符串，采用逗号隔开</returns>
        [HttpGet("getfiles")]
        public string GetFiles(string parentDir)
        {
            // 返回值
            StringBuilder restr = new StringBuilder();
            if (!string.IsNullOrWhiteSpace(parentDir))
            {
                // 配置文件信息集合
                List<ConfigFileInfoModel> configFileInfos = new List<ConfigFileInfoModel>();
                // 配置文件信息表对应的数据层
                DAL_ConfigFile dAL_ConfigFile = new DAL_ConfigFile();

                // 获取功能的ID,根据功能ID获取其下属的文件
                DAL_ProgramNavicat navicat = new DAL_ProgramNavicat();
                long programid = navicat.GetProgramIdByCode(parentDir);
                List<ProgramNavicatModel> childProgramInfos = navicat.GetChildProgram(programid);
                if (childProgramInfos.Count == 0)
                {
                    configFileInfos = dAL_ConfigFile.GetConfigFiles(programid);
                }
                else
                {
                    long programId = childProgramInfos.Where(a => a.Code == parentDir).FirstOrDefault().ID;
                    // 根据功能ID找到配置文件集合
                    configFileInfos = dAL_ConfigFile.GetConfigFiles(programId);
                }
                // 组装返回结果
                foreach (var item in configFileInfos)
                {
                    // 不显示结构化配置文件(其特点是文件名有固定的后缀_struct)
                    if (item.name.IndexOf("_struct") == -1)
                    {
                        string fileName = item.parentPath + "/" + item.name + "-" + item.name + ":" + item.note;
                        restr = restr.Append(fileName + ",");
                    }
                }
                //去掉最后一个,
                if (restr.ToString().Substring(restr.Length - 1, 1) == ",")
                {
                    string tempCatch = restr.ToString().Substring(0, restr.Length - 1);
                    restr.Clear();
                    restr.Append(tempCatch);
                }
            }
            return restr.ToString();
        }

        /// <summary>
        /// 在流程配置文件添加步骤或是修改步骤的保存方法
        /// </summary>
        /// <returns></returns>
        [HttpPost("udpitem")]
        public string UdpItem()
        {
            //获取用户信息
            UserInfoModel user = new UserInfoModel();
            var userJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["user"]);
            user = Newtonsoft.Json.JsonConvert.DeserializeObject<UserInfoModel>(userJsonStr);
            //获取版本信息
            VersionModel version = new VersionModel();
            var versionJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["version"]);
            version = Newtonsoft.Json.JsonConvert.DeserializeObject<VersionModel>(versionJsonStr);
            var versionPath = version?.Catalogue == "dev"
                                ? ""
                                : version?.Catalogue;
            //ViewBag.fileName = Request.Form["processCfgName"];
            var processType = Request.Form["processType"].ToString();
            #region  流程配置文件步骤模型实体赋值
            StepF processCfgItemInfo = new StepF();
            // 模块文件名称
            processCfgItemInfo.fileName = Request.Form["fileName"].ToString().Replace("\\", "/");
            // 序号
            processCfgItemInfo.number = Request.Form["number"];
            // 执行方式
            processCfgItemInfo.executetype = "file";
            // 这里用":"做分隔符，是因为前端页面的显示方式是 文件名:文件说明，所以这里使用:分割，取文件名
            string moudleCfgN = Request.Form["fileName"];
            string fName = Path.GetFileName(moudleCfgN);
            processCfgItemInfo.executecode = fName;
            // 备注
            processCfgItemInfo.zh_cn = Request.Form["zh_cn"];

            processCfgItemInfo.executefile = processCfgItemInfo.fileName;
            // 设置模块的code信息
            if (Request.Form["moduleInfo"].ToString().IndexOf("_") > -1)
            {
                processCfgItemInfo.code = Request.Form["moduleInfo"].ToString().Split('_')[1];
            }
            else
            {
                processCfgItemInfo.code = Request.Form["moduleInfo"];
            }

            processCfgItemInfo.steptype = 2;
            processCfgItemInfo.groupstepcode = (string.IsNullOrWhiteSpace(Request.Form["groupStepCode"].ToString()))
                                             ? ""
                                             : Request.Form["groupStepCode"].ToString();

            #endregion

            // 根据文件路径打开文件
            string fileName = Base64Helper.DeCodeBase64(65001, Request.Form["processCfgName"]);

            // 根据number属性找到step的节点，之后跟该节点的属性值
            string fileNameTemp = Path.Combine(configRootPath, versionPath, fileName);
            if (System.IO.File.Exists(fileNameTemp))
            {
                FileInfo fileInfo = new FileInfo(fileNameTemp);
                try
                {
                    // 读取配置文件，并查找到number=json数据传过来的number，之后删除查找到的节点
                    string configContent = FileSecret.DecryptFileToContent(fileNameTemp);
                    XDocument xdocument = XDocument.Parse(configContent);
                    XElement root = xdocument.Element("root");
                    List<XElement> stepNodes = root.Descendants().Where(x => x.Name.LocalName == "step").ToList();
                    List<XElement> filterRe = stepNodes.Where(a => a.Attribute("number").Value == processCfgItemInfo.number).ToList();
                    if (filterRe.Count == 0)
                    {
                        // 如果当前传入的节点在流程配置文件中找不到就添加节点
                        XElement newNode = new XElement("step");
                        newNode.SetAttributeValue("number", processCfgItemInfo.number);
                        newNode.SetAttributeValue("executefile", processCfgItemInfo.executefile.Replace("\\","/"));
                        newNode.SetAttributeValue("executetype", processCfgItemInfo.executetype);
                        newNode.SetAttributeValue("executecode", processCfgItemInfo.executecode);
                        newNode.SetAttributeValue("code", processCfgItemInfo.code);
                        newNode.SetAttributeValue("zh_cn", processCfgItemInfo.zh_cn);
                        newNode.SetAttributeValue("groupstepcode", processCfgItemInfo.groupstepcode);
                        newNode.SetAttributeValue("steptype", processCfgItemInfo.steptype);
                        XElement processNode = root.Element(processType);
                        if (!string.IsNullOrWhiteSpace(processCfgItemInfo.groupstepcode))
                        {
                            var groupCode = processCfgItemInfo.groupstepcode;
                            XElement groupNode = root.Descendants().FirstOrDefault(x => x.Name.LocalName == "groupstep" && x.Attribute("code").Value == groupCode);
                            int start = Convert.ToInt32(groupNode.Attribute("start").Value);
                            int end = Convert.ToInt32(groupNode.Attribute("end").Value);
                            if (groupNode.HasElements)
                            {
                                groupNode.LastNode.AddAfterSelf(newNode);
                                groupNode.Attribute("end").Value = (end + 1).ToString();
                            }
                            else
                            {
                                groupNode.Add(newNode);
                            }

                        }
                        else
                        {
                            if (processNode.HasElements)
                            {
                                processNode.LastNode.AddAfterSelf(newNode);
                            }
                            else
                            {
                                processNode.Add(newNode);
                            }
                        }

                        xdocument.Save(fileNameTemp);
                        this.EncryptFileToFile(fileNameTemp, fileNameTemp);
                        CreateMoudleNode(fileName, processCfgItemInfo.executefile, processCfgItemInfo.zh_cn, processCfgItemInfo.code);
                        _log.WriteLog(LogHelper.logType.Debug, "ProcessCfgFileController---UdpFile方法：流程配置文件" + fileName + "添加了number=" + processCfgItemInfo.number + "的项!");
                        _log.WriteLog(LogHelper.logType.Info, $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}用户{user.Name}在流程配置文件{fileName}中添加了number={processCfgItemInfo.number }的配置项!");
                        // 更新在对应的模块下的索引文件
                        UpdateMoudleIndex(fileNameTemp, "N", Convert.ToInt32(processCfgItemInfo.number), processCfgItemInfo.groupstepcode, processType);
                    }
                    else
                    {
                        // 如果当前传入的节点在流程配置文件中能找到就更新节点
                        foreach (XAttribute attribute in filterRe[0].Attributes())
                        {
                            if (attribute.Name.ToString() == "number")
                                attribute.Value = processCfgItemInfo.number;
                            if (attribute.Name.ToString() == "executefile")
                                attribute.Value = processCfgItemInfo.executefile.Replace("\\","/");
                            if (attribute.Name.ToString() == "executetype")
                                attribute.Value = processCfgItemInfo.executetype;
                            if (attribute.Name.ToString() == "executecode")
                                attribute.Value = processCfgItemInfo.executecode;
                            if (attribute.Name.ToString() == "code")
                                attribute.Value = processCfgItemInfo.code;
                            if (attribute.Name.ToString() == "zh_cn")
                                attribute.Value = processCfgItemInfo.zh_cn;
                        }
                        _log.WriteLog(LogHelper.logType.Debug, "ProcessCfgFileController---UdpFile方法：流程配置文件" + fileName + "中number=" + processCfgItemInfo.number + "被修改了!");

                        _log.WriteLog(LogHelper.logType.Info, $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}用户{user.Name}在流程配置文件{fileName }中修改了number={processCfgItemInfo.number}的配置项!");
                        xdocument.Save(fileNameTemp);
                        this.EncryptFileToFile(fileNameTemp, fileNameTemp);
                    }

                }
                catch (Exception ex)
                {
                    _log.WriteLog(LogHelper.logType.Error, "ProcessCfgFileController---UdpFile方法：流程配置文件" + fileName + "被更新时报错,错误信息=" + ex.Message);
                }
            }
            return "success";
        }

        /// <summary>
        /// 添加流程配置文件
        /// </summary>
        /// <param name="dir">文件目录</param>
        /// <returns></returns>
        [HttpGet("addfile")]
        public ActionResult AddFile(string dir)
        {
            //获取用户信息
            UserInfoModel user = new UserInfoModel();
            DAL_DataSource sourceDal = new DAL_DataSource();
            var userJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["user"]);
            user = Newtonsoft.Json.JsonConvert.DeserializeObject<UserInfoModel>(userJsonStr);
            //获取版本信息
            VersionModel version = new VersionModel();
            var versionJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["version"]);
            version = Newtonsoft.Json.JsonConvert.DeserializeObject<VersionModel>(versionJsonStr);
            var versionPath = version?.Catalogue == "dev"
                                ? ""
                                : version?.Catalogue;
            dir = dir.Replace("\\", "/");
            var dirList = dir.Split('/').ToList();
            // 流程配置文件信息
            List<ConfigFileInfoModel> processCfgFileInfos = new List<ConfigFileInfoModel>();

            // 根据入参获取案件类型
            string caseTypeCode = Path.GetFileNameWithoutExtension(dir);
            Expression<Func<DataSource, bool>> sourceWhere = null;
            sourceWhere = sourceWhere.And(x => x.CaseTypeCode == caseTypeCode);
            var sourceList = sourceDal.GetDataSourceByFilter(sourceWhere);
            return new JsonResult(sourceList);
        }

        /// <summary>
        /// 保存新建的流程配置文件
        /// </summary>
        /// <returns></returns>
        [HttpPost("savefile")]
        public string SaveFile()
        {
            DAL_ProgramNavicat navicat = new DAL_ProgramNavicat();
            DAL_ConfigFile configFileDal = new DAL_ConfigFile();
            //获取用户信息
            UserInfoModel user = new UserInfoModel();
            var userJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["user"]);
            user = Newtonsoft.Json.JsonConvert.DeserializeObject<UserInfoModel>(userJsonStr);
            DAL_UserInfo userDal = new DAL_UserInfo();
            string rid = userDal.GetUserRid(user.Id);
            //获取版本信息
            VersionModel version = new VersionModel();
            var versionJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["version"]);
            version = Newtonsoft.Json.JsonConvert.DeserializeObject<VersionModel>(versionJsonStr);
            var versionPath = version?.Catalogue == "dev"
                                ? ""
                                : version?.Catalogue;
            // 获取流程配置的文件结构
            //文件名称
            string fileName = Request.Form["filename"];
            //添加类型
            string type = Request.Form["type"];
            string explain = Request.Form["explain"];
            //父级路径
            string parentDir = Request.Form["dir"];
            //
            string caseType = Path.GetFileName(parentDir);
            //文书名称
            string docName = Request.Form["docName"];


            string fileParentPath = $"{parentDir}/{docName.ToLower()}";
            if (string.IsNullOrEmpty(fileName))
            {
                return "err文件名不可为空";
            }
            //保存的XML的地址
            if (fileName.IndexOf(".") > -1)
            {
                fileName = fileName.Substring(0, fileName.IndexOf(".")) + ".xml";
            }
            else
            {
                fileName = fileName + ".xml";
            }
            string sourceFullPath = Path.Combine(configRootPath, versionPath, fileParentPath);
            if(!Directory.Exists(sourceFullPath))
            {
                Directory.CreateDirectory(sourceFullPath);
                ConfigFiles configFile = configFileDal.GetConfigFileByPath(fileParentPath);
                if(configFile==null)
                {
                    DAL_DataSource sourceDal = new DAL_DataSource();
                    var sourceInfo= sourceDal.GetDataSourceByCode(docName.ToLower(), caseType);
                    var parentConfig = configFileDal.GetConfigFileByPath(parentDir);
                    configFile = new ConfigFiles();
                    configFile.Currentid = System.Guid.NewGuid().ToString("N");
                    configFile.Programid = parentConfig.Programid;
                    configFile.Parentid = parentConfig.Currentid;
                    configFile.Level = parentConfig.Level + 1;
                    configFile.Name = docName.ToLower();
                    configFile.Ctype = "D";
                    configFile.Path = $"{parentConfig.Path}/{docName.ToLower()}";
                    configFile.ParentPath = parentDir;
                    configFile.Filesize = string.Empty;
                    configFile.Createdtime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                    configFile.Updatetime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                    configFile.Status = "1";
                    configFile.Note = sourceInfo.Name;
                    configFileDal.InsertConfig(configFile);
                    #region 更新菜单统计数量
                    DAL_ProgramNavicat navicatDal = new DAL_ProgramNavicat();
                    var nav = navicatDal.GetNavicatById(parentConfig.Programid.Value);
                    if (nav != null)
                    {
                        DAL_MenuStatistics statisticsDal = new DAL_MenuStatistics();
                        //修改当前菜单文件数量
                        statisticsDal.FloderNumIncremental(nav.Id);

                        //修改父级菜单文件数量
                        var allParentId = nav.AllParentId;
                        if (!string.IsNullOrWhiteSpace(allParentId))
                        {
                            List<string> parentids = allParentId.Split(",").Reverse().ToList();
                            foreach (var id in parentids)
                            {
                                long navId = Int64.Parse(id);
                                statisticsDal.FloderNumIncremental(navId);
                            }
                        }
                    }
                    #endregion
                }

            }


            //文件相对路径
            string fileRelativePath = Path.Combine(fileParentPath, fileName);
            //文件全路径
            string fileFullPath = Path.Combine(configRootPath,versionPath,fileRelativePath);
            if (System.IO.File.Exists(fileFullPath))
            {
                _log.WriteLog(LogHelper.logType.Debug, "ProcessCfgFileController---SaveFile方法:用户输入的文件名" + fileRelativePath + "已经存在。");
                return "err文件已经存在";
            }
            else
            {
                XmlDocument xmlDoc = new XmlDocument();
                XmlNode node = xmlDoc.CreateXmlDeclaration("1.0", "utf-8", "");
                xmlDoc.AppendChild(node);
                XmlNode root = xmlDoc.CreateElement("root");
                xmlDoc.AppendChild(root);
                XmlAttribute xAttributeType = xmlDoc.CreateAttribute("type");
                xAttributeType.Value = type;
                XmlAttribute xAttributeExplain = xmlDoc.CreateAttribute("explain");
                xAttributeExplain.Value = explain;
                root.Attributes.Append(xAttributeType);
                root.Attributes.Append(xAttributeExplain);
                XmlElement analysis = xmlDoc.CreateElement("analysis");
                root.AppendChild(analysis);
                XmlElement optimize = xmlDoc.CreateElement("optimize");
                root.AppendChild(optimize);
                xmlDoc.Save(fileFullPath);
                this.EncryptFileToFile(fileFullPath, fileFullPath);
                CreateProcessNode(caseType, docName, fileRelativePath);
                var programid = navicat.GetProgramId(parentDir);
                SaveFileInfoToDb(fileFullPath, fileParentPath, fileName, programid,explain);
                _log.WriteLog(LogHelper.logType.Debug, "ProcessCfgFileController---SaveFile方法:文件" + fileFullPath + "保存成功。");
                RefreshStatistics(user.Name, rid);
                return "success";
            }
        }

        /// <summary>
        /// 删除流程配置文件
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>

        [HttpPost("delfile")]
        public IActionResult DelFile(string fileName)
        {
            //获取用户信息
            UserInfoModel user = new UserInfoModel();
            var userJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["user"]);
            user = Newtonsoft.Json.JsonConvert.DeserializeObject<UserInfoModel>(userJsonStr);
            DAL_UserInfo userDal = new DAL_UserInfo();
            string rid = userDal.GetUserRid(user.Id);
            //获取版本信息
            VersionModel version = new VersionModel();
            var versionJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["version"]);
            version = Newtonsoft.Json.JsonConvert.DeserializeObject<VersionModel>(versionJsonStr);
            var versionPath = version?.Catalogue == "dev"
                                ? ""
                                : version?.Catalogue;
            string fileNameFull = Path.Combine(configRootPath, versionPath, fileName).Replace("\\", "/");
            string backPath = Path.Combine(backupRootPath, versionPath, fileName).Replace("\\", "/");
            // 对要删除的文件重命名
            FileInfo fi = new FileInfo(fileNameFull);
            try
            {
                if (!Directory.Exists(Path.GetDirectoryName(backPath)))
                    Directory.CreateDirectory(Path.GetDirectoryName(backPath));
                fi.MoveTo(backPath + "back" + DateTime.Now.ToString("yyyyMMddHHmmss"));
                DeleteProcessNode(fileName);
                DAL_ProgramNavicat navicatDal = new DAL_ProgramNavicat();
                DAL_ConfigFile configFileDal = new DAL_ConfigFile();
                var configFileInfo = configFileDal.GetConfigFileByPath(fileName);
                if(configFileDal.ExistFile(fileName)>0)
                {
                    configFileDal.DeleteConfigFile(fileName);
                    var nav = navicatDal.GetNavicatById(configFileInfo.Programid.Value);
                    if (nav != null)
                    {
                        DAL_MenuStatistics statisticsDal = new DAL_MenuStatistics();
                        //修改当前菜单文件数量
                        statisticsDal.FileNumDecrement(nav.Id);

                        //修改父级菜单文件数量
                        var allParentId = nav.AllParentId;
                        if (!string.IsNullOrWhiteSpace(allParentId))
                        {
                            List<string> parentids = allParentId.Split(",").Reverse().ToList();
                            foreach (var id in parentids)
                            {
                                long navId = Int64.Parse(id);
                                statisticsDal.FileNumDecrement(navId);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                var erroMessage = ex.Message;
            }
           
            _log.WriteLog(LogHelper.logType.Debug, "MoudleCfgController-DelFile方法：删除" + fileName + "文件！系统将该文将重命名为" + fileName + "back" + DateTime.Now.ToString("yyyyMMddHHmmss"));
            // 数据中删除该文件的记录
            fileName = fileName.Replace("\\", "/");
            _log.WriteLog(LogHelper.logType.Debug, "MoudleCfgController-DelFile方法：删除文件" + fileName + "数据库记录");
            DAL_ConfigFile dAL_ConfigFile = new DAL_ConfigFile();
            var delResult= dAL_ConfigFile.DeleteConfigFile(fileName);
            _log.WriteLog(LogHelper.logType.Info, $"{ DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}用户{user.Name}删除文件{fileName}{(delResult>0 ? "成功":"失败")}");
            RefreshStatistics(user.Name, rid);
            return new JsonResult(new { code = 0, msg = "删除成功" });
        }

        /// <summary>
        /// 删除数据源文件夹
        /// </summary>
        [HttpPost("deldatasource")]
        public IActionResult DelDataSource(string sourcePath)
        {
            int resultCode = 0;
            string resultMsg = string.Empty;
            //获取用户信息
            UserInfoModel user = new UserInfoModel();
            var userJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["user"]);
            user = Newtonsoft.Json.JsonConvert.DeserializeObject<UserInfoModel>(userJsonStr);
            DAL_UserInfo userDal = new DAL_UserInfo();
            string rid = userDal.GetUserRid(user.Id);
            //获取版本信息
            VersionModel version = new VersionModel();
            var versionJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["version"]);
            version = Newtonsoft.Json.JsonConvert.DeserializeObject<VersionModel>(versionJsonStr);
            var versionPath = version?.Catalogue == "dev"
                                ? ""
                                : version?.Catalogue;
            var sourceFullPath = Path.Combine(configRootPath, versionPath, sourcePath).Replace("\\","/");
            DAL_ConfigFile configFileDal = new DAL_ConfigFile();
            DAL_ProgramNavicat navicatDal = new DAL_ProgramNavicat();
            try
            {
                if (Directory.Exists(sourceFullPath))
                {

                    Expression<Func<ConfigFiles, bool>> configWhere = null;
                    configWhere = configWhere.And(x => x.ParentPath == sourcePath);
                    var sourceChilds = configFileDal.GetConfigFilesByFilter(configWhere);
                    if (sourceChilds != null && sourceChilds.Any())
                    {
                        resultMsg = "请先删除该数据源下配置";
                    }
                    else
                    {
                        configWhere = null;
                        Directory.Delete(sourceFullPath);
                        var sourceConfig = configFileDal.GetConfigFileByPath(sourcePath);
                        if (sourceConfig != null)
                        {
                            configFileDal.DeleteConfigFile(sourcePath);
                            var nav = navicatDal.GetNavicatById(sourceConfig.Programid.Value);
                            if (nav != null)
                            {
                                DAL_MenuStatistics statisticsDal = new DAL_MenuStatistics();
                                //修改当前菜单文件数量
                                statisticsDal.FloderNumDecrement(nav.Id);

                                //修改父级菜单文件数量
                                var allParentId = nav.AllParentId;
                                if (!string.IsNullOrWhiteSpace(allParentId))
                                {
                                    List<string> parentids = allParentId.Split(",").Reverse().ToList();
                                    foreach (var id in parentids)
                                    {
                                        long navId = Int64.Parse(id);
                                        statisticsDal.FloderNumDecrement(navId);
                                    }
                                }
                            }
                            RefreshStatistics(user.Name, rid);
                            resultCode = 1;
                            resultMsg = "删除成功";
                        }
                        else
                        {
                            resultMsg = "该数据源不存在或已被删除";
                        }
                    }
                }
                else
                {
                    resultMsg = "该数据源目录不存在或已被删除";
                }
            }
            catch (Exception ex)
            {
                resultMsg = $"删除数据源异常：{ex.ToString()}";
                _log.WriteLog(LogHelper.logType.Info, $"{ DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}用户{user.Name}删除数据源文件夹{sourcePath}异常：{ex.ToString()}");
            }
            _log.WriteLog(LogHelper.logType.Info, $"{ DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}用户{user.Name}删除数据源文件夹{sourcePath}{(resultCode > 0 ? "成功" : "失败")}");
            return new JsonResult(new { code = resultCode, msg = resultMsg });
        }
        



        /// <summary>
        /// 下载文件
        /// </summary>
        /// <param name="fileName">文件名</param>
        /// <returns></returns>
        [HttpGet("downloadfile")]
        public ActionResult DownLoadFile(string fileName)
        {
            //获取用户信息
            UserInfoModel user = new UserInfoModel();
            var userJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["user"]);
            user = Newtonsoft.Json.JsonConvert.DeserializeObject<UserInfoModel>(userJsonStr);
            //获取版本信息
            VersionModel version = new VersionModel();
            var versionJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["version"]);
            version = Newtonsoft.Json.JsonConvert.DeserializeObject<VersionModel>(versionJsonStr);
            var versionPath = version?.Catalogue == "dev"
                                ? ""
                                : version?.Catalogue;
            Result re = new Result();
            if (!string.IsNullOrEmpty(fileName))
            {
                re.code = "1";
                string filenameTemp = Path.Combine(configRootPath, versionPath, fileName).Replace("\\", "/");
                string clientFileName = Path.GetFileName(fileName);
                string fileContent = FileSecret.DecryptFileToContent(filenameTemp);
                byte[] bytes = Encoding.UTF8.GetBytes(fileContent);
                //二进制流数据（如常见的文件下载）
                return File(bytes, "application/octet-stream", clientFileName);
            }
            else
            {
                re.code = "0";
                re.message = "下载失败";
                return BadRequest(re);
            }
        }

        /// <summary>
        /// 优选流程添加分组模块
        /// </summary>
        [HttpPost("addgroupitem")]
        public IActionResult AddGroupItem()
        {
            //获取用户信息
            UserInfoModel user = new UserInfoModel();
            var userJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["user"]);
            user = Newtonsoft.Json.JsonConvert.DeserializeObject<UserInfoModel>(userJsonStr);
            //获取版本信息
            VersionModel version = new VersionModel();
            var versionJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["version"]);
            version = Newtonsoft.Json.JsonConvert.DeserializeObject<VersionModel>(versionJsonStr);
            var versionPath = version?.Catalogue == "dev"
                                ? ""
                                : version?.Catalogue;
            #region  流程配置文件步骤模型实体赋值
            Groupstep step = new Groupstep();
            //分组模块编号
            step.Code = Request.Form["code"].ToString();
            //分组模块中文备注
            step.Zh_cn = Request.Form["zh_ch"].ToString();
            //模块类型 1 普通模块 2 分组模块
            step.StepType = Convert.ToByte(Request.Form["stepType"]);
            string processType = Request.Form["processType"].ToString();
            #endregion

            // 根据文件路径打开文件
            string fileName = Base64Helper.DeCodeBase64(65001, Request.Form["processCfgName"]);

            // 根据number属性找到step的节点，之后跟该节点的属性值
            string fileNameTemp = Path.Combine(configRootPath, versionPath, fileName);
            if (System.IO.File.Exists(fileNameTemp))
            {
                FileInfo fileInfo = new FileInfo(fileNameTemp);
                try
                {
                    // 读取配置文件，并查找到number=json数据传过来的number，之后删除查找到的节点
                    string configContent = FileSecret.DecryptFileToContent(fileNameTemp);
                    XDocument xdocument = XDocument.Parse(configContent);
                    var rootNode = xdocument.Element("root");
                    if (rootNode != null)
                    {
                        XElement processNode = rootNode.Element(processType);
                        int index = 0;
                        if (processType == "analysis")
                        {
                            List<XElement> stepList = processNode.Descendants().Where(x => x.Name.LocalName == "step").ToList();
                            if (stepList != null && stepList.Any())
                                index = Convert.ToInt32(stepList.OrderByDescending(x => Convert.ToInt32(x.Attribute("number").Value)).FirstOrDefault()?.Attribute("number").Value);
                        }
                        else if (processType == "optimize")
                        {
                            List<XElement> steps = rootNode.Descendants().Where(x => x.Name.LocalName == "step").ToList();
                            if (steps != null && steps.Any())
                                index = Convert.ToInt32(steps.OrderByDescending(x =>Convert.ToInt32(x.Attribute("number").Value)).FirstOrDefault()?.Attribute("number").Value);
                        }

                        XElement groupNode = new XElement("groupstep");
                        groupNode.SetAttributeValue("code", step.Code);
                        groupNode.SetAttributeValue("zh_ch", step.Zh_cn);
                        groupNode.SetAttributeValue("steptype", step.StepType);
                        groupNode.SetAttributeValue("start", index + 1);
                        groupNode.SetAttributeValue("end", index + 1);
                        if (processNode.HasElements)
                        {
                            xdocument.Element("root").Element(processType).LastNode.AddAfterSelf(groupNode);
                        }
                        else
                        {
                            xdocument.Element("root").Element(processType).Add(groupNode);
                        }

                        _log.WriteLog(LogHelper.logType.Info, $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}用户{user.Name}在流程配置文件{fileName}中添加了Code={step.Code }的分组配置项!");
                    }
                    xdocument.Save(fileNameTemp);
                    this.EncryptFileToFile(fileNameTemp, fileNameTemp);
                }
                catch (Exception ex)
                {
                    _log.WriteLog(LogHelper.logType.Error, "ProcessCfgFileController---AddGroupItem方法：流程配置文件" + fileName + "被更新时报错,错误信息=" + ex.Message);
                }
            }
            return new JsonResult(new { code = 0, msg = "添加成功" });
        }

        /// <summary>
        /// 将文件信息保存到数据库中
        /// </summary>
        /// <param name="fullPath">文件全路径</param>
        /// <param name="fileParentPath">文件相对路径</param>
        /// <param name="fileName">文件名称</param>
        /// <param name="programid">programid</param>
        /// <param name="explain">文件备注</param>
        private void SaveFileInfoToDb(string fullPath,string fileParentPath,string fileName,long programid,string explain)
        {
            DAL_ConfigFile dAL_ConfigFile = new DAL_ConfigFile();
            // 现判断该文件是否存在
            string fileRelativePath = Path.Combine(fileParentPath, fileName);
            int re = dAL_ConfigFile.ExistFile(fileRelativePath);
            if (re <= 0)
            {
                FileInfo fileInfo = new FileInfo(fullPath);
                string currentId = System.Guid.NewGuid().ToString("N");
                var parentConfig = dAL_ConfigFile.GetConfigFileByPath(fileParentPath);
                ConfigFiles model = new ConfigFiles();
                model.Currentid = currentId;
                model.Programid = programid;
                model.Parentid = parentConfig.Currentid;
                model.Level = parentConfig.Level + 1;
                model.Name = fileInfo.Name;
                model.Ctype = "F";
                model.Path = fileRelativePath;
                model.ParentPath = fileParentPath;
                model.Filesize = fileInfo.Length.ToString() + "B";
                model.Createdtime= fileInfo.CreationTime.ToString("yyyy-MM-dd HH:mm:ss");
                model.Updatetime = fileInfo.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss");
                model.Status = "1";
                model.Note = explain;
                dAL_ConfigFile.InsertConfig(model);
                #region 更新菜单统计数量
                DAL_ProgramNavicat navicatDal = new DAL_ProgramNavicat();
                var nav = navicatDal.GetNavicatById(programid);
                if(nav!=null)
                {
                    DAL_MenuStatistics statisticsDal = new DAL_MenuStatistics();
                    //修改当前菜单文件数量
                    statisticsDal.FileNumIncremental(nav.Id);
                    
                    //修改父级菜单文件数量
                    var allParentId = nav.AllParentId;
                    if(!string.IsNullOrWhiteSpace(allParentId))
                    {
                        List<string> parentids = allParentId.Split(",").Reverse().ToList();
                        foreach (var id in parentids)
                        {
                            long navId = Int64.Parse(id);
                            statisticsDal.FileNumIncremental(navId);
                        }
                    }
                }
                #endregion

            }
        }

        /// <summary>
        /// 加密文件，输入源文件路径返回加密后文件路径
        /// </summary>
        /// <param name="inFileName">明文文件路径</param>
        /// <param name="outFileName">密文文件路径</param>
        private void EncryptFileToFile(string inFileName, string outFileName)
        {
            if (inFileName == outFileName)
            {
                string enFileName = Path.GetDirectoryName(inFileName) + "_" + Path.GetFileName(inFileName);
                FileSecret.EncryptFile(inFileName, enFileName);
                System.IO.File.Delete(inFileName);
                System.IO.File.Copy(enFileName, inFileName);
                System.IO.File.Delete(enFileName);
            }
            else
            {
                FileSecret.EncryptFile(inFileName, outFileName);
            }
        }

        /// <summary>
        /// 更新流程配置文件模块配置索引
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <param name="operateFlag">操作类型 D删除 N添加</param>
        /// <param name="current">当前模块索引</param>
        /// <param name="groupCode">分组编号</param>
        /// <param name="processType">流程类型</param>

        private void UpdateMoudleIndex(string filePath, string operateFlag, int current, string groupCode, string processType)
        {
            if (System.IO.File.Exists(filePath))
            {
                FileInfo fileInfo = new FileInfo(filePath);
                string configContent = FileSecret.DecryptFileToContent(filePath);
                XDocument xdocument = XDocument.Parse(configContent);
                XElement root = xdocument.Element("root");
                if (operateFlag == "N")
                {
                    XElement currentNode = root.Descendants().FirstOrDefault(x => x.Name.LocalName == "step" && x.Attribute("number").Value == current.ToString());
                    if (!string.IsNullOrWhiteSpace(groupCode))
                    {
                        var groupNode = root.Descendants().FirstOrDefault(x => x.Name.LocalName == "groupstep" && x.Attribute("code").Value == groupCode);

                        List<XElement> groupSteps = groupNode.Elements().Where(x => x.Attribute("number").Value != current.ToString()).ToList();
                        int end = Convert.ToInt32(groupNode.Attribute("end").Value);
                        int next = end;

                        List<XElement> updateSteps = root.Descendants().Where(x => x.Name.LocalName == "step" && Convert.ToInt32(x.Attribute("number").Value) >= end).ToList();

                        foreach (XElement sp in updateSteps.Where(x => x.Attribute("number").Value != current.ToString()))
                        {
                            next += 1;
                            sp.Attribute("number").Value = next.ToString();
                        }
                        currentNode.Attribute("number").Value = end.ToString();
                    }
                    else
                    {
                        int last = 0;
                        XElement processNode = root.Element(processType);
                        List<XElement> steps = processNode.Descendants().Where(x => x.Name.LocalName == "step" && x.Attribute("number").Value != current.ToString()).ToList();
                        if (steps != null && steps.Any())
                        {
                            var maxStepNode = steps.OrderByDescending(x =>Convert.ToInt32( x.Attribute("number").Value)).FirstOrDefault();
                            last = Convert.ToInt32(maxStepNode.Attribute("number").Value);
                            int next = last + 1;
                            List<XElement> updateSteps = root.Descendants().Where(x => x.Name.LocalName == "step" && Convert.ToInt32(x.Attribute("number").Value) > last).OrderBy(x=>Convert.ToInt32(x.Attribute("number").Value)).ToList();
                            foreach (XElement sp in updateSteps.Where(x => x.Attribute("number").Value != current.ToString()))
                            {
                                next += 1;
                                sp.Attribute("number").Value = next.ToString();
                            }

                            currentNode.Attribute("number").Value = (last + 1).ToString();
                        }
                        else { 
                            if(processType=="analysis")
                            {
                                currentNode.Attribute("number").Value = "1";
                                XElement optimizeNode = root.Element("optimize");
                                List<XElement> optimzieSteps = optimizeNode.Descendants().Where(x => x.Name.LocalName == "step").OrderBy(x => Convert.ToInt32(x.Attribute("number").Value)).ToList();
                                if (optimzieSteps != null && optimzieSteps.Any())
                                {
                                    optimzieSteps.ForEach(x => x.Attribute("number").Value = (Convert.ToInt32(x.Attribute("number").Value) + 1).ToString());
                                }
                                
                            }
                        }
                    }
                }
                else if (operateFlag == "D")
                {
                    List<XElement> updateSteps = root.Descendants().Where(x => x.Name.LocalName == "step" && Convert.ToInt32(x.Attribute("number").Value) > current).ToList();
                    if (updateSteps != null && updateSteps.Any())
                    {
                        foreach (XElement sp in updateSteps.Where(x => x.Attribute("number").Value != current.ToString()))
                        {
                            int old = Convert.ToInt32(sp.Attribute("number").Value);
                            sp.Attribute("number").Value = (old - 1).ToString();
                        }
                    }
                }
                List<XElement> updateGroupSteps = root.Descendants()
                                                           .Where(x => x.Name.LocalName == "groupstep")
                                                           .ToList();
                if (updateGroupSteps != null && updateGroupSteps.Any())
                {
                    foreach (XElement gsp in updateGroupSteps)
                    {
                        List<XElement> gsteps = gsp.Descendants().Where(x => x.Name.LocalName == "step").ToList();
                        if (gsteps != null && gsteps.Any())
                        {
                            XElement startStep = gsteps.OrderBy(x =>Convert.ToInt32(x.Attribute("number").Value)).FirstOrDefault();
                            gsp.Attribute("start").Value = startStep.Attribute("number").Value;
                            XElement endStep = gsteps.OrderByDescending(x =>Convert.ToInt32(x.Attribute("number").Value)).FirstOrDefault();
                            gsp.Attribute("end").Value = startStep.Attribute("number").Value;

                        }
                    }
                }


                xdocument.Save(filePath);
                this.EncryptFileToFile(filePath, filePath);
            }
        }


        /// <summary>
        /// 移动流程文件中Step模块
        /// </summary>
        /// <param name="fileName">文件名</param>
        /// <returns></returns>
        [HttpPost("moveitem")]
        public IActionResult MoveItem(string fileName)
        {
            try
            {
                //获取用户信息
                UserInfoModel user = new UserInfoModel();
                var userJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["user"]);
                user = Newtonsoft.Json.JsonConvert.DeserializeObject<UserInfoModel>(userJsonStr);
                //获取版本信息
                VersionModel version = new VersionModel();
                var versionJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["version"]);
                version = Newtonsoft.Json.JsonConvert.DeserializeObject<VersionModel>(versionJsonStr);
                var versionPath = version?.Catalogue == "dev"
                                    ? ""
                                    : version?.Catalogue;
                string operate = string.Empty;
                fileName = Request.Form["fileName"];
                string processType = Request.Form["processType"];
                string groupCode = Request.Form["groupCode"];
                int current = Convert.ToInt32(Request.Form["current"]);
                string operateFlag = Request.Form["operateFlag"];
                string fileFullName = Path.Combine(configRootPath, versionPath, fileName);
                if (System.IO.File.Exists(fileFullName))
                {
                    FileInfo fileInfo = new FileInfo(fileFullName);
                    string configContent = FileSecret.DecryptFileToContent(fileFullName);
                    XDocument xdocument = XDocument.Parse(configContent);
                    XElement root = xdocument.Element("root");
                    int max = 0;
                    int min = 0;
                    if (!string.IsNullOrWhiteSpace(groupCode))
                    {
                        XElement groupStep = root.Descendants().FirstOrDefault(x => x.Name.LocalName == "groupstep" && x.Attribute("code").Value == groupCode);
                        min = Convert.ToInt32(groupStep.Attribute("start").Value);
                        max = Convert.ToInt32(groupStep.Attribute("end").Value);
                    }
                    else
                    {
                        XElement processNode = root.Element(processType);
                        List<XElement> steps = processNode.Descendants().Where(x => x.Name.LocalName == "step").ToList();
                        XElement minNode = steps.OrderBy(x =>Convert.ToInt32(x.Attribute("number").Value)).FirstOrDefault();
                        XElement maxNode = steps.OrderByDescending(x =>Convert.ToInt32(x.Attribute("number").Value)).FirstOrDefault();
                        min = Convert.ToInt32(minNode.Attribute("number").Value);
                        max = Convert.ToInt32(maxNode.Attribute("number").Value);
                    }

                    if ((operateFlag == "1" && current > min) || (operateFlag == "2" && current < max))
                    {
                        XElement currentNode = root.Descendants().FirstOrDefault(x => x.Name.LocalName == "step" && x.Attribute("number").Value == current.ToString());
                        string currentGroupCode = currentNode.Attribute("groupstepcode").Value;
                        XElement adjacentNode = null;
                        
                        if (operateFlag == "1")
                        {

                            adjacentNode = root.Descendants()
                                               .Where(x => x.Name.LocalName == "step")
                                               .Where(x => Convert.ToInt32(x.Attribute("number").Value) < current)
                                               .OrderByDescending(x => Convert.ToInt32(x.Attribute("number").Value))
                                               .FirstOrDefault();
                            operate = "上移";
                        }
                        else if (operateFlag == "2")
                        {
                            adjacentNode = root.Descendants()
                                               .Where(x => x.Name.LocalName == "step")
                                               .Where(x => Convert.ToInt32(x.Attribute("number").Value) > current)
                                               .OrderBy(x => Convert.ToInt32(x.Attribute("number").Value))
                                               .FirstOrDefault();
                            operate = "下移";
                        }

                        string adjacentNumber = adjacentNode.Attribute("number").Value;
                        var groupCodeAttr = adjacentNode.Attributes().Where(x => x.Name == "groupstepcode").FirstOrDefault();
                        string adjacentGroupCode = string.Empty;
                        if (groupCodeAttr !=null)
                        {
                            adjacentGroupCode = adjacentNode.Attribute("groupstepcode").Value;
                        }
                        if (!string.IsNullOrWhiteSpace(adjacentGroupCode) && adjacentGroupCode != currentGroupCode)
                        {
                            if (operateFlag == "1")
                            {
                                XElement adjacentGroupNode = root.Descendants().FirstOrDefault(x => x.Name.LocalName == "groupstep" && x.Attribute("end").Value == adjacentNumber);

                                List<XElement> adjacentStepList = adjacentGroupNode.Elements().ToList();
                                foreach (XElement asp in adjacentStepList)
                                {
                                    int number = Convert.ToInt32(asp.Attribute("number").Value);
                                    asp.Attribute("number").Value = (number + 1).ToString();
                                }
                                string newStart = adjacentStepList.OrderBy(x =>Convert.ToInt32(x.Attribute("number").Value)).FirstOrDefault().Attribute("number").Value;
                                string newEnd = adjacentStepList.OrderByDescending(x =>Convert.ToInt32(x.Attribute("number").Value)).FirstOrDefault().Attribute("number").Value; ;
                                adjacentGroupNode.Attribute("start").Value = newStart.ToString();
                                adjacentGroupNode.Attribute("end").Value = newEnd.ToString();
                                currentNode.Attribute("number").Value = (Convert.ToInt32(newStart) - 1).ToString();
                            }
                            else if (operateFlag == "2")
                            {
                                XElement adjacentGroupNode = root.Descendants().FirstOrDefault(x => x.Name.LocalName == "groupstep" && x.Attribute("start").Value == adjacentNumber);

                                List<XElement> adjacentStepList = adjacentGroupNode.Elements().ToList();
                                foreach (XElement asp in adjacentStepList)
                                {
                                    int number = Convert.ToInt32(asp.Attribute("number").Value);
                                    asp.Attribute("number").Value = (number - 1).ToString();
                                }
                                string newStart = adjacentStepList.OrderBy(x =>Convert.ToInt32(x.Attribute("number").Value)).FirstOrDefault().Attribute("number").Value;
                                string newEnd = adjacentStepList.OrderByDescending(x =>Convert.ToInt32(x.Attribute("number").Value)).FirstOrDefault().Attribute("number").Value;
                                adjacentGroupNode.Attribute("start").Value = newStart;
                                adjacentGroupNode.Attribute("end").Value = newEnd;
                                currentNode.Attribute("number").Value = (Convert.ToInt32(newEnd) + 1).ToString();
                            }

                        }
                        else
                        {
                            adjacentNode.Attribute("number").Value = current.ToString();
                            currentNode.Attribute("number").Value = adjacentNumber;
                        }
                        xdocument.Save(fileFullName);
                        this.EncryptFileToFile(fileFullName, fileFullName);
                        _log.WriteLog(LogHelper.logType.Info, $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}用户{user.Name}{operate}了流程配置文件{fileName}中number={current}的配置项!");
                    }
                    return new JsonResult(ReturnInfo.Success("成功"));
                }
                else
                {
                    return new JsonResult(ReturnInfo.Fail("未找到相关文件"));
                }
            }
            catch (Exception ex)
            {
                return new JsonResult(ReturnInfo.Fail($"异常：{ex.Message}"));
            }

        }

        /// <summary>
        /// 移动流程文件中GroupStep模块
        /// </summary>
        [HttpPost("movegroupitem")]
        public IActionResult MoveGroupItem(string fileName)
        {
            try
            {
                //获取用户信息
                UserInfoModel user = new UserInfoModel();
                var userJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["user"]);
                user = Newtonsoft.Json.JsonConvert.DeserializeObject<UserInfoModel>(userJsonStr);
                //获取版本信息
                VersionModel version = new VersionModel();
                var versionJsonStr = Base64Helper.DeCodeBase64(65001, Request.Headers["version"]);
                version = Newtonsoft.Json.JsonConvert.DeserializeObject<VersionModel>(versionJsonStr);
                var versionPath = version?.Catalogue == "dev"
                                    ? ""
                                    : version?.Catalogue;

                string operate = string.Empty;
                fileName = Request.Form["fileName"];
                string processType = Request.Form["processType"];
                string groupCode = Request.Form["groupCode"];
                string operateFlag = Request.Form["operateFlag"];
                string fileFullName = Path.Combine(configRootPath, versionPath, fileName);
                bool isMove = true;

                if (System.IO.File.Exists(fileFullName))
                {
                    FileInfo fileInfo = new FileInfo(fileFullName);
                    string configContent = FileSecret.DecryptFileToContent(fileFullName);
                    XDocument xdocument = XDocument.Parse(configContent);
                    XElement root = xdocument.Element("root");
                    int max = 0;
                    int min = 0;
                    if (!string.IsNullOrWhiteSpace(groupCode))
                    {
                        XElement processNode = root.Element(processType);
                        List<XElement> steps = processNode.Descendants().Where(x => x.Name.LocalName == "step").ToList();
                        if (steps != null && steps.Any())
                        {
                            XElement minStep = steps.OrderBy(x =>Convert.ToInt32(x.Attribute("number").Value)).FirstOrDefault();
                            XElement maxStep = steps.OrderByDescending(x =>Convert.ToInt32(x.Attribute("number").Value)).FirstOrDefault();
                            min = Convert.ToInt32(minStep.Attribute("number").Value);
                            max = Convert.ToInt32(maxStep.Attribute("number").Value);
                        }
                        else
                        {
                            isMove = false;
                        }


                        XElement groupNode = root.Descendants().FirstOrDefault(x => x.Name.LocalName == "groupstep" && x.Attribute("code").Value == groupCode);
                        int start = Convert.ToInt32(groupNode.Attribute("start").Value);
                        int end = Convert.ToInt32(groupNode.Attribute("end").Value);

                        if ((operateFlag == "1" && start > min && isMove) || (operateFlag == "2" && end < max && isMove))
                        {
                            string adjacentNumber = string.Empty;
                            int newNumber = 0;
                            if (operateFlag == "1")
                            {
                                adjacentNumber = (start - 1).ToString();
                                newNumber = end;
                                operate = "上移";
                                groupNode.Attribute("start").Value = (start - 1).ToString();
                                groupNode.Attribute("end").Value = (end - 1).ToString();
                            }
                            else if (operateFlag == "2")
                            {
                                adjacentNumber = (end + 1).ToString();
                                newNumber = start;
                                operate = "下移";
                                groupNode.Attribute("start").Value = (start + 1).ToString();
                                groupNode.Attribute("end").Value = (end + 1).ToString();
                            }

                            XElement adjacentStep = root.Descendants().FirstOrDefault(x => x.Name.LocalName == "step" && x.Attribute("number").Value == adjacentNumber);
                            if (!string.IsNullOrWhiteSpace(adjacentStep.Attribute("groupstepcode").Value))
                            {
                                if (operateFlag == "1")
                                {
                                    XElement adjacentGroupNode = root.Descendants().FirstOrDefault(x => x.Name.LocalName == "groupstep" && x.Attribute("end").Value == adjacentNumber);

                                    List<XElement> adjacentStepList = adjacentGroupNode.Elements().ToList();
                                    foreach (XElement asp in adjacentStepList)
                                    {
                                        int number = Convert.ToInt32(adjacentGroupNode.Attribute("number").Value);

                                        asp.Attribute("number").Value = (number + 1).ToString();
                                    }
                                    string newStart = (Convert.ToInt32(adjacentGroupNode.Attribute("start").Value) + 1).ToString();
                                    string newEnd = (Convert.ToInt32(adjacentGroupNode.Attribute("end").Value) + 1).ToString();
                                    adjacentGroupNode.Attribute("start").Value = newStart;
                                    adjacentGroupNode.Attribute("end").Value = newEnd;
                                }
                                else if (operateFlag == "2")
                                {
                                    XElement adjacentGroupNode = root.Descendants().FirstOrDefault(x => x.Name.LocalName == "groupstep" && x.Attribute("start").Value == adjacentNumber);

                                    List<XElement> adjacentStepList = adjacentGroupNode.Elements().ToList();
                                    foreach (XElement asp in adjacentStepList)
                                    {
                                        int number = Convert.ToInt32(asp.Attribute("number").Value);
                                        asp.Attribute("number").Value = (number - 1).ToString();
                                    }
                                    string newStart = (Convert.ToInt32(adjacentGroupNode.Attribute("start").Value) - 1).ToString();
                                    string newEnd = (Convert.ToInt32(adjacentGroupNode.Attribute("end").Value) - 1).ToString();
                                    adjacentGroupNode.Attribute("start").Value = newStart;
                                    adjacentGroupNode.Attribute("end").Value = newEnd;

                                }
                            }
                            else
                            {
                                adjacentStep.Attribute("number").Value = newNumber.ToString();
                            }

                            List<XElement> groupSteps = groupNode.Elements().ToList();
                            foreach (XElement gs in groupSteps)
                            {
                                int current = Convert.ToInt32(gs.Attribute("number").Value);
                                if (operateFlag == "1")
                                {
                                    gs.Attribute("number").Value = (current - 1).ToString();
                                }
                                else if (operateFlag == "2")
                                {
                                    gs.Attribute("number").Value = (current + 1).ToString();
                                }

                            }
                        }
                        xdocument.Save(fileFullName);
                        this.EncryptFileToFile(fileFullName, fileFullName);
                        _log.WriteLog(LogHelper.logType.Info, $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}用户{user.Name}{operate}了流程配置文件{fileName}中Code={groupCode}的分组配置项!");
                    }
                    return new JsonResult(ReturnInfo.Success("成功"));
                }
                else
                {
                    return new JsonResult(ReturnInfo.Fail("未找到相关文件"));
                }
            }
            catch (Exception ex)
            {
                return new JsonResult(ReturnInfo.Fail($"异常：{ex.Message}"));
            }
        }

        /// <summary>
        /// 全流程配置添加流程节点
        /// </summary>
        private void CreateProcessNode(string caseCode,string docType,string processPath)
        {
            var fileName = $"{configRootPath}/config/wholeprocess.xml";
            processPath = processPath.Replace("\\", "/");
            var wholeContent = System.IO.File.ReadAllText(fileName);
            XDocument xdocument = XDocument.Parse(wholeContent);
            var rootNode = xdocument.Element("root");
            XElement caseType = rootNode.Descendants()
                                        .FirstOrDefault(x => x.Name.LocalName == "casetype" && x.Attribute("code").Value == caseCode);
            DAL_DataSource sourceDal = new DAL_DataSource();
            if(caseType!=null)
            {
                XElement docTypeNode = caseType.Descendants()
                                             .Where(x => x.Name.LocalName == "doctype")
                                             .Where(x => x.Attribute("code").Value == docType)
                                             .FirstOrDefault();
                if(docTypeNode==null)
                {
                    //获取卷宗名称
                    var docName = string.Empty;
                    var sourceInfo = sourceDal.GetDataSourceByCode(docType.ToLower(), caseCode);
                    if (sourceInfo != null)
                        docName = sourceInfo.Name;
                    docTypeNode = new XElement("doctype");
                    docTypeNode.SetAttributeValue("name", docName);
                    docTypeNode.SetAttributeValue("code", docType);
                    docTypeNode.SetAttributeValue("parentcode", caseCode);
                    caseType.Add(docTypeNode);
                }

                var processName= Path.GetFileName(processPath);

                XElement processNode = new XElement("process");
                processNode.SetAttributeValue("name", processName);
                processNode.SetAttributeValue("path", processPath.Replace("\\","/"));
                processNode.SetAttributeValue("parentcode", $"{caseCode}_{docType}");
                docTypeNode.Add(processNode);
            }
            xdocument.Save(fileName);
        }

        /// <summary>
        /// 删除全流程配置流程节点
        /// </summary>
        private void DeleteProcessNode(string processPath)
        {
            //config / processconfig / analysisprocessconfig / z / drslla / test.xml
            if(!string.IsNullOrWhiteSpace(processPath))
            {
                string removePath = processPath.Replace("\\","/");
                var fileName = $"{configRootPath}/config/wholeprocess.xml";
                var wholeContent = System.IO.File.ReadAllText(fileName);
                XDocument xdocument = XDocument.Parse(wholeContent);
                var rootNode = xdocument.Element("root");
                var processNode = rootNode.Descendants()
                                        .Where(x => x.Name.LocalName == "process")
                                        .Where(x => x.Attribute("path").Value == removePath)
                                        .FirstOrDefault();
                if (processNode != null)
                    processNode.Remove();
                xdocument.Save(fileName);
            }
            
        }

        private void CreateMoudleNode(string processPath, string modulePath,string remark,string moduleCode)
        {
            var fileName = $"{configRootPath}/config/wholeprocess.xml";
            processPath = processPath.Replace("\\", "/");
            var wholeContent = System.IO.File.ReadAllText(fileName);
            XDocument xdocument = XDocument.Parse(wholeContent);
            var rootNode = xdocument.Element("root");

            XElement processNode = rootNode.Descendants()
                                        .Where(x => x.Name.LocalName == "process")
                                        .Where(x => x.Attribute("path").Value == processPath)
                                        .FirstOrDefault();
            if(processNode!=null)
            {
                var processName = processNode.Attribute("name").Value;
                var processCode = processNode.Attribute("parentcode").Value;
                modulePath = modulePath.Replace("\\", "/");
                var moduleName = Path.GetFileName(modulePath);
                XElement moduleNode = new XElement("module");
                moduleNode.SetAttributeValue("name", moduleName);
                moduleNode.SetAttributeValue("code", moduleCode);
                moduleNode.SetAttributeValue("path", modulePath);
                moduleNode.SetAttributeValue("remark", remark);
                moduleNode.SetAttributeValue("parentcode", $"{processCode}_{processName}");
                processNode.Add(moduleNode);
            }
            xdocument.Save(fileName);
        }

        /// <summary>
        /// 删除全流程配置模块节点
        /// </summary>
        private void DeleteModuleNode(string processPath,string modulePath,string moduleCode)
        {

            var fileName = $"{configRootPath}/config/wholeprocess.xml";
            processPath = processPath.Replace("\\", "/");
            var wholeContent = System.IO.File.ReadAllText(fileName);
            XDocument xdocument = XDocument.Parse(wholeContent);
            var rootNode = xdocument.Element("root");
            XElement processNode = rootNode.Descendants()
                                        .Where(x => x.Name.LocalName == "process")
                                        .Where(x => x.Attribute("path").Value == processPath)
                                        .FirstOrDefault();
            if (processNode != null)
            {
                modulePath = modulePath.Replace("\\", "/");
                var moduleNode = processNode.Descendants()
                                          .Where(x => x.Name.LocalName == "module")
                                          .Where(x => x.Attribute("path").Value == modulePath)
                                          .Where(x => x.Attribute("code").Value == moduleCode)
                                          .FirstOrDefault();
                if (moduleNode != null)
                    moduleNode.Remove();
            }
            xdocument.Save(fileName);
        }

        /// <summary>
        /// 刷新配置文件统计数量s
        /// </summary>
        private void RefreshStatistics(string userName, string rid)
        {
            DAL_ConfigFile configFileDal = new DAL_ConfigFile();
            DAL_ProgramNavicat programNavicatDal = new DAL_ProgramNavicat();
            var configFileList = configFileDal.GetDeskStatistics();
            var desk = new
            {
                totalfilesnum = configFileList.TotalNum,
                processcfgfilesnum = configFileList.processCfgFilesNum,
                mlcfigfilenum = configFileList.MLCfigFileNum,
                modulecfgfilenum = configFileList.moduleCfgFileNum,
                todayaddfiles = configFileList.todayAddFiles
            };
            var navicats = programNavicatDal.GetProtramNavicatTree(userName, rid);
            var message = new { desk = desk, menus = navicats };
            var serializersettings = new JsonSerializerSettings
            {

                // 设置为驼峰命名

                ContractResolver = new CamelCasePropertyNamesContractResolver()

            };
            hubMessageServer.SendMessage(JsonConvert.SerializeObject(message,Newtonsoft.Json.Formatting.None,serializersettings));
        }

    }
}
